#include "EZ_Thread.h"

void ipc_object_init(ez_ipc_t *ipc)
{
	list_init(&ipc->suspend_thread);
}

void ipc_object_insert(ez_ipc_t *ipc,ez_thread_t *thread)
{
	task_suspend(thread);

	list_insert_before(&ipc->suspend_thread,&thread->tlist);
	
}

void ipc_object_wait(ez_ipc_t *ipc,ez_thread_t *thread,uint32_t time)
{
  ipc_object_insert(ipc,thread);
  timer_contorl(&thread->timer,EZ_TIME_CTRL_SET_TIME,(void *)time);
  timer_start(&thread->timer);
}

void ipc_resume(list_t *suspend_list) 
{
	ez_thread_t *thread;
	
	thread = get_list_entry(suspend_list->next,ez_thread_t,tlist);
	task_resume(thread);
	
}

void ipc_resume_all(list_t *suspend_list)
{
	list_t *tmp_list;
	ez_thread_t *thread;

	
	tmp_list = suspend_list;
	while(suspend_list != tmp_list->next)
	{
		thread = get_list_entry(tmp_list->next,ez_thread_t,tlist);
		task_resume(thread);
		tmp_list = tmp_list->next;
	}
	
}

uint8_t ipc_isempty(ez_ipc_t *ipc)
{
	return list_isempty(&ipc->suspend_thread);

}

void sem_object_init(ez_ipc_sem_t * sem,uint32_t value)
{
	ipc_object_init(&sem->ipc);
	sem->vaule = value;
}
uint32_t sem_get_value(ez_ipc_sem_t * sem)
{
	 return sem->vaule;
}


uint32_t sem_task(ez_ipc_sem_t * sem,uint32_t time)
{
	uint32_t state;
	ez_thread_t *thread;
	state = ez_hw_interrupt_disable();
	
	if(sem->vaule >0)
	{
		sem->vaule--;
	}
	else
	{
		if(time != 0)
		{ 
			thread = get_thread_self();
      ipc_object_wait(&sem->ipc,thread,time);
			ez_hw_interrupt_enable(state);
			task_scheduler();
			sem_task(sem,0);
		}
	}
	
	ez_hw_interrupt_enable(state);
	return EZ_TRUE;
}

uint32_t sem_release(ez_ipc_sem_t * sem)
{
	uint32_t state;
	state = ez_hw_interrupt_disable();
	
	if(list_isempty(&sem->ipc.suspend_thread) == EZ_TRUE)
	{
		sem->vaule++;
	}
	else
	{
		ipc_resume(&sem->ipc.suspend_thread);
		ez_hw_interrupt_enable(state);
		task_scheduler();
	}
	
	ez_hw_interrupt_enable(state);
	return EZ_TRUE;
}
